using System;
using System.Collections.Generic;



public struct EventOwner
{
    private List<Delegate> _eventHandlers;
    private Dictionary<Type, List<Delegate>> _eventHandlersByType;
    private Dictionary<(Type, Type), List<Delegate>> _eventHandlersByTwoType;
    private Dictionary<(Type, Type, Type), List<Delegate>> _eventHandlersByThreeType;
    private Dictionary<(Type, Type, Type, Type), List<Delegate>> _eventHandlersByFourType;
    private Dictionary<(Type, Type, Type, Type, Type), List<Delegate>> _eventHandlersByFiveType;

    // 注册事件处理程序
    public void Register(Action handler)
    {
        if (handler == null)
        {
            return;
        }
        // 检查是否是Lambda表达式
        if (handler.Target == null || IsAnonymousMethod(handler))
        {
            throw new InvalidOperationException("不支持注册Lambda表达式作为事件处理器。");
        }
        if (_eventHandlers == null)
        {
            _eventHandlers = new List<Delegate>();
        }
        _eventHandlers.Add(handler);
    }

    public void Register<T>(Action<T> handler)
    {
        if (handler == null)
        {
            return;
        }
        // 检查是否是Lambda表达式
        if (handler.Target == null || IsAnonymousMethod(handler))
        {
            throw new InvalidOperationException("不支持注册Lambda表达式作为事件处理器。");
        }
        if (_eventHandlersByType == null)
        {
            _eventHandlersByType = new Dictionary<Type, List<Delegate>>();
        }
        Type type = typeof(T);
        if (_eventHandlersByType.ContainsKey(type))
        {
            _eventHandlersByType[type].Add(handler);
        }
        else
        {
            _eventHandlersByType[type] = new List<Delegate> { handler };
        }
    }

    public void Register<T1, T2>(Action<T1, T2> handler)
    {
        if (handler == null)
        {
            return;
        }
        // 检查是否是Lambda表达式
        if (handler.Target == null || IsAnonymousMethod(handler))
        {
            throw new InvalidOperationException("不支持注册Lambda表达式作为事件处理器。");
        }
        if (_eventHandlersByTwoType == null)
        {
            _eventHandlersByTwoType = new Dictionary<(Type, Type), List<Delegate>>();
        }
        var key = (typeof(T1), typeof(T2));
        if (_eventHandlersByTwoType.ContainsKey(key))
        {
            _eventHandlersByTwoType[key].Add(handler);
        }
        else
        {
            _eventHandlersByTwoType[key] = new List<Delegate> { handler };
        }
    }

    public void Register<T1, T2, T3>(Action<T1, T2, T3> handler)
    {
        if (handler == null)
        {
            return;
        }
        // 检查是否是Lambda表达式
        if (handler.Target == null || IsAnonymousMethod(handler))
        {
            throw new InvalidOperationException("不支持注册Lambda表达式作为事件处理器。");
        }
        if (_eventHandlersByThreeType == null)
        {
            _eventHandlersByThreeType = new Dictionary<(Type, Type, Type), List<Delegate>>();
        }
        var key = (typeof(T1), typeof(T2), typeof(T3));
        if (_eventHandlersByThreeType.ContainsKey(key))
        {
            _eventHandlersByThreeType[key].Add(handler);
        }
        else
        {
            _eventHandlersByThreeType[key] = new List<Delegate> { handler };
        }
    }

    public void Register<T1, T2, T3, T4>(Action<T1, T2, T3, T4> handler)
    {
        if (handler == null)
        {
            return;
        }
        // 检查是否是Lambda表达式
        if (handler.Target == null || IsAnonymousMethod(handler))
        {
            throw new InvalidOperationException("不支持注册Lambda表达式作为事件处理器。");
        }
        if (_eventHandlersByFourType == null)
        {
            _eventHandlersByFourType = new Dictionary<(Type, Type, Type, Type), List<Delegate>>();
        }
        var key = (typeof(T1), typeof(T2), typeof(T3), typeof(T4));
        if (_eventHandlersByFourType.ContainsKey(key))
        {
            _eventHandlersByFourType[key].Add(handler);
        }
        else
        {
            _eventHandlersByFourType[key] = new List<Delegate> { handler };
        }
    }

    public void Register<T1, T2, T3, T4, T5>(Action<T1, T2, T3, T4, T5> handler)
    {
        if (handler == null)
        {
            return;
        }
        // 检查是否是Lambda表达式
        if (handler.Target == null || IsAnonymousMethod(handler))
        {
            throw new InvalidOperationException("不支持注册Lambda表达式作为事件处理器。");
        }
        if (_eventHandlersByFiveType == null)
        {
            _eventHandlersByFiveType = new Dictionary<(Type, Type, Type, Type, Type), List<Delegate>>();
        }
        var key = (typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5));
        if (_eventHandlersByFiveType.ContainsKey(key))
        {
            _eventHandlersByFiveType[key].Add(handler);
        }
        else
        {
            _eventHandlersByFiveType[key] = new List<Delegate> { handler };
        }
    }

    public static bool IsAnonymousMethod(Delegate method)
    {
        return method.Method.DeclaringType == null ||
               method.Method.IsSpecialName ||
               method.Method.Name.Contains("<>") ||
               method.Method.DeclaringType.Name.Contains("<>");
    }

    // 注销事件处理程序
    public void Unregister(Action handler)
    {
        if (_eventHandlers == null)
            return;
        for (int i = _eventHandlers.Count - 1; i >= 0; i--)
        {
            if (DelegateEquals(_eventHandlers[i], handler))
            {
                _eventHandlers.RemoveAt(i);
            }
        }
    }

    public void Unregister<T>(Action<T> handler)
    {
        if (_eventHandlersByType == null)
            return;
        Type type = typeof(T);
        if (_eventHandlersByType.TryGetValue(type, out var handlers))
        {
            if (handlers == null)
            {
                return;
            }
            for (int i = handlers.Count - 1; i >= 0; i--)
            {
                if (DelegateEquals(handlers[i], handler))
                {
                    handlers.RemoveAt(i);
                }
            }
        }
    }

    public void Unregister<T1, T2>(Action<T1, T2> handler)
    {
        if (_eventHandlersByTwoType == null)
            return;
        var key = (typeof(T1), typeof(T2));
        if (_eventHandlersByTwoType.TryGetValue(key, out var handlers))
        {
            if (handlers == null)
            {
                return;
            }
            for (int i = handlers.Count - 1; i >= 0; i--)
            {
                if (DelegateEquals(handlers[i], handler))
                {
                    handlers.RemoveAt(i);
                }
            }
        }
    }

    public void Unregister<T1, T2, T3>(Action<T1, T2, T3> handler)
    {
        if (_eventHandlersByThreeType == null)
            return;
        var key = (typeof(T1), typeof(T2), typeof(T3));
        if (_eventHandlersByThreeType.TryGetValue(key, out var handlers))
        {
            if (handlers == null)
            {
                return;
            }
            for (int i = handlers.Count - 1; i >= 0; i--)
            {
                if (DelegateEquals(handlers[i], handler))
                {
                    handlers.RemoveAt(i);
                }
            }
        }
    }

    public void Unregister<T1, T2, T3, T4>(Action<T1, T2, T3, T4> handler)
    {
        if (_eventHandlersByFourType == null)
            return;
        var key = (typeof(T1), typeof(T2), typeof(T3), typeof(T4));
        if (_eventHandlersByFourType.TryGetValue(key, out var handlers))
        {
            if (handlers == null)
            {
                return;
            }
            for (int i = handlers.Count - 1; i >= 0; i--)
            {
                if (DelegateEquals(handlers[i], handler))
                {
                    handlers.RemoveAt(i);
                }
            }
        }
    }

    public void Unregister<T1, T2, T3, T4, T5>(Action<T1, T2, T3, T4, T5> handler)
    {
        if (_eventHandlersByFiveType == null)
            return;
        var key = (typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5));
        if (_eventHandlersByFiveType.TryGetValue(key, out var handlers))
        {
            if (handlers == null)
            {
                return;
            }
            for (int i = handlers.Count - 1; i >= 0; i--)
            {
                if (DelegateEquals(handlers[i], handler))
                {
                    handlers.RemoveAt(i);
                }
            }
        }
    }

    private bool DelegateEquals(Delegate d1, Delegate d2)
    {
        if (d1 == d2) return true;
        if (d1 == null || d2 == null) return false;

        return d1.Method == d2.Method &&
               d1.Target == d2.Target;
    }

    public void UnregisterOfTarget(object target)
    {
        UnregisterOfTargetFromList(target, _eventHandlers);
        foreach (var list in _eventHandlersByType.Values)
        {
            UnregisterOfTargetFromList(target, list);
        }
        foreach (var list in _eventHandlersByTwoType.Values)
        {
            UnregisterOfTargetFromList(target, list);
        }
        foreach (var list in _eventHandlersByThreeType.Values)
        {
            UnregisterOfTargetFromList(target, list);
        }
        foreach (var list in _eventHandlersByFourType.Values)
        {
            UnregisterOfTargetFromList(target, list);
        }
        foreach (var list in _eventHandlersByFiveType.Values)
        {
            UnregisterOfTargetFromList(target, list);
        }
    }

    private void UnregisterOfTargetFromList(object target, List<Delegate> handlers)
    {
        if (handlers == null || handlers.Count == 0)
        {
            return;
        }
        for (int i = handlers.Count - 1; i >= 0; i--)
        {
            var handler = handlers[i];
            if (handler != null && handler.Target == target)
            {
                handlers.RemoveAt(i);
            }
        }
    }

    // 触发事件
    public void Trigger()
    {
        if (_eventHandlers != null)
        {
            var count = _eventHandlers.Count;
            for (int i = 0; i < count; i++)
            {
                if (_eventHandlers[i] == null)
                {
                    continue;
                }
                var action = _eventHandlers[i] as Action;
                if (action != null && action.Target != null)
                {
                    action.Invoke();
                }
            }
        }
    }

    public void Trigger<T>(T arg1)
    {
        if (_eventHandlersByType != null)
        {
            Type type = typeof(T);
            if (_eventHandlersByType.TryGetValue(type, out var handlers))
            {
                if (handlers != null)
                {
                    var count = handlers.Count;
                    for (int i = 0; i < count; i++)
                    {
                        if (handlers[i] == null)
                        {
                            continue;
                        }
                        var action = handlers[i] as Action<T>;
                        if (action != null && action.Target != null)
                        {
                            action.Invoke(arg1);
                        }
                    }
                }
            }
        }
    }

    public void Trigger<T1, T2>(T1 arg1, T2 arg2)
    {
        if (_eventHandlersByTwoType != null)
        {
            var key = (typeof(T1), typeof(T2));
            if (_eventHandlersByTwoType.TryGetValue(key, out var handlers))
            {
                if (handlers != null)
                {
                    var count = handlers.Count;
                    for (int i = 0; i < count; i++)
                    {
                        if (handlers[i] == null)
                        {
                            continue;
                        }
                        var action = handlers[i] as Action<T1, T2>;
                        if (action != null && action.Target != null)
                        {
                            action.Invoke(arg1, arg2);
                        }
                    }
                }
            }
        }
    }

    public void Trigger<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3)
    {
        if (_eventHandlersByThreeType != null)
        {
            var key = (typeof(T1), typeof(T2), typeof(T3));
            if (_eventHandlersByThreeType.TryGetValue(key, out var handlers))
            {
                if (handlers != null)
                {
                    var count = handlers.Count;
                    for (int i = 0; i < count; i++)
                    {
                        if (handlers[i] == null)
                        {
                            continue;
                        }
                        var action = handlers[i] as Action<T1, T2, T3>;
                        if (action != null && action.Target != null)
                        {
                            action.Invoke(arg1, arg2, arg3);
                        }
                    }
                }
            }
        }
    }

    public void Trigger<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4)
    {
        if (_eventHandlersByFourType != null)
        {
            var key = (typeof(T1), typeof(T2), typeof(T3), typeof(T4));
            if (_eventHandlersByFourType.TryGetValue(key, out var handlers))
            {
                if (handlers != null)
                {
                    var count = handlers.Count;
                    for (int i = 0; i < count; i++)
                    {
                        if (handlers[i] == null)
                        {
                            continue;
                        }
                        var action = handlers[i] as Action<T1, T2, T3, T4>;
                        if (action != null && action.Target != null)
                        {
                            action.Invoke(arg1, arg2, arg3, arg4);
                        }
                    }
                }
            }
        }
    }

    public void Trigger<T1, T2, T3, T4, T5>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)
    {
        if (_eventHandlersByFiveType != null)
        {
            var key = (typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5));
            if (_eventHandlersByFiveType.TryGetValue(key, out var handlers))
            {
                if (handlers != null)
                {
                    var count = handlers.Count;
                    for (int i = 0; i < count; i++)
                    {
                        if (handlers[i] == null)
                        {
                            continue;
                        }
                        var action = handlers[i] as Action<T1, T2, T3, T4, T5>;
                        if (action != null && action.Target != null)
                        {
                            action.Invoke(arg1, arg2, arg3, arg4, arg5);
                        }
                    }
                }
            }
        }
    }

    public void Clear()
    {
        _eventHandlers?.Clear();
        _eventHandlersByType?.Clear();
        _eventHandlersByTwoType?.Clear();
        _eventHandlersByThreeType?.Clear();
        _eventHandlersByFourType?.Clear();
        _eventHandlersByFiveType?.Clear();
    }
}

public class EventManager : Singleton<EventManager>, ISingleton
{
    // 低频场景使用类型来标识事件
    private Dictionary<object, EventOwner> _dicEventOwnerTypes = new Dictionary<object, EventOwner>();
    // 高频场景使用ID来标识事件
    private Dictionary<int, EventOwner> _dicEventOwnerIds = new Dictionary<int, EventOwner>();

    private static readonly Type INT_TYPE = typeof(int);

    private readonly object _lock = new object();

    // 注册事件
    public void RegisterEvent<T>(T key, Action callback)
    {
        lock (_lock)
        {
            Type type = key.GetType();
            if (type == INT_TYPE)
            {
                int id = Convert.ToInt32(key);
                if (GetOwner(id, out var owner))
                {
                    owner.Register(callback);
                }
            }
            else
            {
                if (GetOwner<T>(key, out var owner))
                {
                    owner.Register(callback);
                }
            }
        }
    }

    public void RegisterEvent<T, V1>(T key, Action<V1> callback)
    {
        lock (_lock)
        {
            Type type = key.GetType();
            if (type == INT_TYPE)
            {
                int id = Convert.ToInt32(key);
                if (GetOwner(id, out var owner))
                {
                    owner.Register(callback);
                }
            }
            else
            {
                if (GetOwner<T>(key, out var owner))
                {
                    owner.Register(callback);
                }
            }
        }
    }

    public void RegisterEvent<T, V1, V2>(T key, Action<V1, V2> callback)
    {
        lock (_lock)
        {
            Type type = key.GetType();
            if (type == INT_TYPE)
            {
                int id = Convert.ToInt32(key);
                if (GetOwner(id, out var owner))
                {
                    owner.Register(callback);
                }
            }
            else
            {
                if (GetOwner<T>(key, out var owner))
                {
                    owner.Register(callback);
                }
            }
        }
    }

    public void RegisterEvent<T, V1, V2, V3>(T key, Action<V1, V2, V3> callback)
    {
        lock (_lock)
        {
            Type type = key.GetType();
            if (type == INT_TYPE)
            {
                int id = Convert.ToInt32(key);
                if (GetOwner(id, out var owner))
                {
                    owner.Register(callback);
                }
            }
            else
            {
                if (GetOwner<T>(key, out var owner))
                {
                    owner.Register(callback);
                }
            }
        }
    }

    public void RegisterEvent<T, V1, V2, V3, V4>(T key, Action<V1, V2, V3, V4> callback)
    {
        lock (_lock)
        {
            Type type = key.GetType();
            if (type == INT_TYPE)
            {
                int id = Convert.ToInt32(key);
                if (GetOwner(id, out var owner))
                {
                    owner.Register(callback);
                }
            }
            else
            {
                if (GetOwner<T>(key, out var owner))
                {
                    owner.Register(callback);
                }
            }
        }
    }

    public void RegisterEvent<T, V1, V2, V3, V4, V5>(T key, Action<V1, V2, V3, V4, V5> callback)
    {
        lock (_lock)
        {
            Type type = key.GetType();
            if (type == INT_TYPE)
            {
                int id = Convert.ToInt32(key);
                if (GetOwner(id, out var owner))
                {
                    owner.Register(callback);
                }
            }
            else
            {
                if (GetOwner<T>(key, out var owner))
                {
                    owner.Register(callback);
                }
            }
        }
    }

    // 注销事件
    public void UnregisterEvent<T>(T key, Action callback)
    {
        lock (_lock)
        {
            Type type = key.GetType();
            if (type == INT_TYPE)
            {
                int id = Convert.ToInt32(key);
                if (GetOwner(id, out var owner))
                {
                    owner.Unregister(callback);
                }
            }
            else
            {
                if (GetOwner<T>(key, out var owner))
                {
                    owner.Unregister(callback);
                }
            }
        }
    }

    public void UnregisterEvent<T, V1>(T key, Action<V1> callback)
    {
        lock (_lock)
        {
            Type type = key.GetType();
            if (type == INT_TYPE)
            {
                int id = Convert.ToInt32(key);
                if (GetOwner(id, out var owner))
                {
                    owner.Unregister(callback);
                }
            }
            else
            {
                if (GetOwner<T>(key, out var owner))
                {
                    owner.Unregister(callback);
                }
            }
        }
    }

    public void UnregisterEvent<T, V1, V2>(T key, Action<V1, V2> callback)
    {
        lock (_lock)
        {
            Type type = key.GetType();
            if (type == INT_TYPE)
            {
                int id = Convert.ToInt32(key);
                if (GetOwner(id, out var owner))
                {
                    owner.Unregister(callback);
                }
            }
            else
            {
                if (GetOwner<T>(key, out var owner))
                {
                    owner.Unregister(callback);
                }
            }
        }
    }

    public void UnregisterEvent<T, V1, V2, V3>(T key, Action<V1, V2, V3> callback)
    {
        lock (_lock)
        {
            Type type = key.GetType();
            if (type == INT_TYPE)
            {
                int id = Convert.ToInt32(key);
                if (GetOwner(id, out var owner))
                {
                    owner.Unregister(callback);
                }
            }
            else
            {
                if (GetOwner<T>(key, out var owner))
                {
                    owner.Unregister(callback);
                }
            }
        }
    }

    public void UnregisterEvent<T, V1, V2, V3, V4>(T key, Action<V1, V2, V3, V4> callback)
    {
        lock (_lock)
        {
            Type type = key.GetType();
            if (type == INT_TYPE)
            {
                int id = Convert.ToInt32(key);
                if (GetOwner(id, out var owner))
                {
                    owner.Unregister(callback);
                }
            }
            else
            {
                if (GetOwner<T>(key, out var owner))
                {
                    owner.Unregister(callback);
                }
            }
        }
    }

    public void UnregisterEvent<T, V1, V2, V3, V4, V5>(T key, Action<V1, V2, V3, V4, V5> callback)
    {
        lock (_lock)
        {
            Type type = key.GetType();
            if (type == INT_TYPE)
            {
                int id = Convert.ToInt32(key);
                if (GetOwner(id, out var owner))
                {
                    owner.Unregister(callback);
                }
            }
            else
            {
                if (GetOwner<T>(key, out var owner))
                {
                    owner.Unregister(callback);
                }
            }
        }
    }

    public void UnregisterEventOfTarget(object target)
    {
        lock (_lock)
        {
            foreach (var owner in _dicEventOwnerTypes.Values)
            {
                owner.UnregisterOfTarget(target);
            }
            foreach (var owner in _dicEventOwnerIds.Values)
            {
                owner.UnregisterOfTarget(target);
            }
        }
    }

    // 触发事件
    public void TriggerEvent<T>(T key)
    {
        Type type = key.GetType();
        if (type == INT_TYPE)
        {
            int id = Convert.ToInt32(key);
            if (GetOwner(id, out var owner))
            {
                owner.Trigger();
            }
        }
        else
        {
            if (GetOwner<T>(key, out var owner))
            {
                owner.Trigger();
            }
        }
    }

    public void TriggerEvent<T, V1>(T key, V1 arg1)
    {
        Type type = key.GetType();
        if (type == INT_TYPE)
        {
            int id = Convert.ToInt32(key);
            if (GetOwner(id, out var owner))
            {
                owner.Trigger(arg1);
            }
        }
        else
        {
            if (GetOwner<T>(key, out var owner))
            {
                owner.Trigger(arg1);
            }
        }
    }

    public void TriggerEvent<T, V1, V2>(T key, V1 arg1, V2 arg2)
    {
        Type type = key.GetType();
        if (type == INT_TYPE)
        {
            int id = Convert.ToInt32(key);
            if (GetOwner(id, out var owner))
            {
                owner.Trigger(arg1, arg2);
            }
        }
        else
        {
            if (GetOwner<T>(key, out var owner))
            {
                owner.Trigger(arg1, arg2);
            }
        }
    }

    public void TriggerEvent<T, V1, V2, V3>(T key, V1 arg1, V2 arg2, V3 arg3)
    {
        Type type = key.GetType();
        if (type == INT_TYPE)
        {
            int id = Convert.ToInt32(key);
            if (GetOwner(id, out var owner))
            {
                owner.Trigger(arg1, arg2, arg3);
            }
        }
        else
        {
            if (GetOwner<T>(key, out var owner))
            {
                owner.Trigger(arg1, arg2, arg3);
            }
        }
    }

    public void TriggerEvent<T, V1, V2, V3, V4>(T key, V1 arg1, V2 arg2, V3 arg3, V4 arg4)
    {
        Type type = key.GetType();
        if (type == INT_TYPE)
        {
            int id = Convert.ToInt32(key);
            if (GetOwner(id, out var owner))
            {
                owner.Trigger(arg1, arg2, arg3, arg4);
            }
        }
        else
        {
            if (GetOwner<T>(key, out var owner))
            {
                owner.Trigger(arg1, arg2, arg3, arg4);
            }
        }
    }

    public void TriggerEvent<T, V1, V2, V3, V4, V5>(T key, V1 arg1, V2 arg2, V3 arg3, V4 arg4, V5 arg5)
    {
        Type type = key.GetType();
        if (type == INT_TYPE)
        {
            int id = Convert.ToInt32(key);
            if (GetOwner(id, out var owner))
            {
                owner.Trigger(arg1, arg2, arg3, arg4, arg5);
            }
        }
        else
        {
            if (GetOwner<T>(key, out var owner))
            {
                owner.Trigger(arg1, arg2, arg3, arg4, arg5);
            }
        }
    }


    public void Dispose()
    {
        _dicEventOwnerTypes.Clear();
        _dicEventOwnerIds.Clear();
    }

    private bool GetOwner<T>(T key, out EventOwner owner)
    {
        if (_dicEventOwnerTypes.ContainsKey(key))
        {
            owner = _dicEventOwnerTypes[key];
            return true;
        }
        owner = default;
        return false;
    }

    private bool GetOwner(int key, out EventOwner owner)
    {
        if (_dicEventOwnerIds.ContainsKey(key))
        {
            owner = _dicEventOwnerIds[key];
            return true;
        }
        owner = default;
        return false;
    }
}
